east – west traffic を NAT Gatway を経由させてみた(VPC 内のサブネット間の通信なのに NAT してみた)
後からついてくるものだ、意味なんてものは。
コンバンハ、千葉(幸)です。まずは以下をご覧ください。
はい。そしてこちらを。
VPC にまつわる通信について、インターネットゲートウェイや仮想プライベートゲーウェイを経由して VPC に入ってくる通信を north - south trafic、 VPC 内部のサブネット間の通信を east - west traffic と呼ぶことがあります。
先日、east - west traffic をより柔軟にルーティングできるアップデートが行われました。従来サブネットルートテーブルでは VPC の CIDR より具体的な宛先を指定したルートの登録はできませんでしたが、それが可能になったというものです。
例えば10.0.0.0/16
という VPC があった場合に、それより具体的な10.0.1.0/24
という宛先を指定したルートを定義できるようになっています。この機能の主な使い道はアプライアンス製品に通信をルーティングさせることであり、そのインスタンスが持つネットワークインターフェース(ENI)をターゲットに指定することが多いかと思います。
「より具体的なルート」におけるターゲットとしてサポートされているのは以下の通りです。
- ゲートウェイロードバランサーエンドポイント
- NAT Gateway
- ネットワークファイアウォールエンドポイント
- ネットワークインターフェース
Example routing options - Amazon Virtual Private Cloud
他の 3 つはまだしも NAT Gateway をターゲットにするのはどういったケースだ……?というのが初見では分かりませんでした。その後も事あるごとに引っ張り出してきては考えていましたが、考えても考えても分からないので、そのうち考えるのを止めました。
「どういう時に使うのかわからないけど、なんか面白そうだからやってみるか」というモチベーションでやってみることにしました。
やりたいことの構成
以下の通りです。
送信元のインスタンスから宛先インスタンスへの通信を行います。その際に直接ルーティングするのでなく NAT Gateway を経由させます。宛先インスタンスから見ると送信元 IP アドレスは NAT Gateway が持つプライベート IP アドレスとなります。
送信元サブネットのルートテーブルで赤編みかけしている部分が「より具体的なルート」を登録しているところです。
パケットの気持ちになって考えると、以下のようになります。
ここでやりたいことができると何が嬉しいのか
すみません、よく分かりません。
環境の準備
先程載せた図の通りの構成を作成しました。IP アドレスは以下のように採番されました。
インスタンスをパブリックサブネットに配置しているのは、Systems Manager 経由で接続したいためです。
EC2 インスタンス
Amazon Linux2 の AMI から立ち上げて、 Systems Manager 経由で接続できるように IAM ロールをセットアップしました。
アタッチしている SecuriryGroup では、VPC (10.0.0.0/16)内からのすべてのトラフィックのインバウンドを許可しています。
NAT Gateway
プライベートタイプの NAT Gateway を作成しました。
% aws ec2 describe-nat-gateways --region ap-northeast-3 --output table ----------------------------------------------------- | DescribeNatGateways | +---------------------------------------------------+ || NatGateways || |+-------------------+-----------------------------+| || ConnectivityType | private || || CreateTime | 2021-09-25T10:50:53+00:00 || || NatGatewayId | nat-0efd1351c899a1d4b || || State | available || || SubnetId | subnet-06139abbf53962d56 || || VpcId | vpc-0e9326bf225102d4e || |+-------------------+-----------------------------+| ||| NatGatewayAddresses ||| ||+---------------------+-------------------------+|| ||| NetworkInterfaceId | eni-0f62ab5dbbe7cffb5 ||| ||| PrivateIp | 10.0.2.149 ||| ||+---------------------+-------------------------+|| ||| Tags ||| ||+------------------+----------------------------+|| ||| Key | Name ||| ||| Value | osaka-NAT ||| ||+------------------+----------------------------+||
今回やりたいことに関しては、パブリックタイプでも問題なく実現できます。(単に EIP が無駄に割り当てられるだけです。)
サブネットルートテーブル
冒頭の図の通りの設定で作成しています。
送信元 サブネット(10.0.0.0/24)用
% aws ec2 describe-route-tables --route-table-ids rtb-0c4b26d537894d810 --region ap-northeast-3 --query 'RouteTables[].Routes' --output table ---------------------------------------------------------------------------------------------------------- | DescribeRouteTables | +----------------------+------------------------+------------------------+--------------------+----------+ | DestinationCidrBlock | GatewayId | NatGatewayId | Origin | State | +----------------------+------------------------+------------------------+--------------------+----------+ | 10.0.1.0/24 | | nat-0efd1351c899a1d4b | CreateRoute | active | | 10.0.0.0/16 | local | | CreateRouteTable | active | | 0.0.0.0/0 | igw-09e9571aa689c8066 | | CreateRoute | active | +----------------------+------------------------+------------------------+--------------------+----------+
宛先サブネット(10.0.1.0/24)用
% aws ec2 describe-route-tables --route-table-ids rtb-0477da6dc8cf13cc0 --region ap-northeast-3 --query 'RouteTables[].Routes' --output table --------------------------------------------------------------------------------- | DescribeRouteTables | +----------------------+-------------------------+--------------------+---------+ | DestinationCidrBlock | GatewayId | Origin | State | +----------------------+-------------------------+--------------------+---------+ | 10.0.0.0/16 | local | CreateRouteTable | active | | 0.0.0.0/0 | igw-09e9571aa689c8066 | CreateRoute | active | +----------------------+-------------------------+--------------------+---------+
NAT Gateway サブネット(10.0.2.0/24)用
% aws ec2 describe-route-tables --route-table-ids rtb-09d8f9c413cda3505 --region ap-northeast-3 --query 'RouteTables[].Routes' --output table --------------------------------------------------------------------- | DescribeRouteTables | +-----------------------+------------+--------------------+---------+ | DestinationCidrBlock | GatewayId | Origin | State | +-----------------------+------------+--------------------+---------+ | 10.0.0.0/16 | local | CreateRouteTable | active | +-----------------------+------------+--------------------+---------+
やってみた
早速やっていきます。
再掲すると各コンポーネントの IP アドレスは以下の通りです。
コンポーネント | IP アドレス |
---|---|
送信元インスタンス | 10.0.0.11 |
宛先インスタンス | 10.0.1.55 |
NAT Gateway | 10.0.2.149 |
送信元インスタンスからの traceroute
traceroute で経由する IP アドレスを確認します。
その前に、宛先インスタンス側で NAT Gatewy の IP を指定して tcpdump を行います。該当する通信があれば、その内訳が出力されていきます。
sh-4.2$ sudo tcpdump -i eth0 host 10.0.2.149 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
送信元インスタンスに切り替え、宛先インスタンスの IP を指定して traceroute を行います。実行時刻が分かるよう date を先に実行しています。
sh-4.2$ date +%H:%M:%S.%6N && traceroute 10.0.1.55 11:17:40.880630 traceroute to 10.0.1.55 (10.0.1.55), 30 hops max, 60 byte packets 1 10.0.2.149 (10.0.2.149) 0.082 ms 0.072 ms 0.063 ms 2 10.0.1.55 (10.0.1.55) 0.423 ms 0.422 ms 0.406 ms sh-4.2$
↑ NAT Gateway(10.0.2.149)を経由したのち、宛先インスタンス(10.0.1.55)に到達していることがわかります。
宛先インスタンス側では、該当する通信が出力されています。
# sh-4.2$ sudo tcpdump -i eth0 host 10.0.2.149 # tcpdump: verbose output suppressed, use -v or -vv for full protocol decode # listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 11:17:40.881952 IP 10.0.2.149.59743 > ip-10-0-1-55.ap-northeast-3.compute.internal.33437: UDP, length 32 11:17:40.881986 IP ip-10-0-1-55.ap-northeast-3.compute.internal > 10.0.2.149: ICMP ip-10-0-1-55.ap-northeast-3.compute.internal udp port 33437 unreachable, length 68 11:17:40.881992 IP 10.0.2.149.62576 > ip-10-0-1-55.ap-northeast-3.compute.internal.33440: UDP, length 32 11:17:40.881995 IP ip-10-0-1-55.ap-northeast-3.compute.internal > 10.0.2.149: ICMP ip-10-0-1-55.ap-northeast-3.compute.internal udp port 33440 unreachable, length 68 11:17:40.881997 IP 10.0.2.149.58860 > ip-10-0-1-55.ap-northeast-3.compute.internal.33439: UDP, length 32 11:17:40.882000 IP ip-10-0-1-55.ap-northeast-3.compute.internal > 10.0.2.149: ICMP ip-10-0-1-55.ap-northeast-3.compute.internal udp port 33439 unreachable, length 68 11:17:40.882002 IP 10.0.2.149.40488 > ip-10-0-1-55.ap-northeast-3.compute.internal.33444: UDP, length 32 11:17:40.882005 IP ip-10-0-1-55.ap-northeast-3.compute.internal > 10.0.2.149: ICMP ip-10-0-1-55.ap-northeast-3.compute.internal udp port 33444 unreachable, length 68 11:17:40.882008 IP 10.0.2.149.39818 > ip-10-0-1-55.ap-northeast-3.compute.internal.33438: UDP, length 32 11:17:40.882011 IP ip-10-0-1-55.ap-northeast-3.compute.internal > 10.0.2.149: ICMP ip-10-0-1-55.ap-northeast-3.compute.internal udp port 33438 unreachable, length 68 11:17:40.882014 IP 10.0.2.149.51062 > ip-10-0-1-55.ap-northeast-3.compute.internal.33441: UDP, length 32 11:17:40.882017 IP ip-10-0-1-55.ap-northeast-3.compute.internal > 10.0.2.149: ICMP ip-10-0-1-55.ap-northeast-3.compute.internal udp port 33441 unreachable, length 68 11:17:40.882019 IP 10.0.2.149.27348 > ip-10-0-1-55.ap-northeast-3.compute.internal.33442: UDP, length 32 11:17:40.882021 IP 10.0.2.149.12585 > ip-10-0-1-55.ap-northeast-3.compute.internal.33443: UDP, length 32 11:17:40.882050 IP 10.0.2.149.31037 > ip-10-0-1-55.ap-northeast-3.compute.internal.33446: UDP, length 32 11:17:40.882054 IP 10.0.2.149.46422 > ip-10-0-1-55.ap-northeast-3.compute.internal.33445: UDP, length 32 11:17:40.882056 IP 10.0.2.149.59721 > ip-10-0-1-55.ap-northeast-3.compute.internal.33447: UDP, length 32 11:17:40.882058 IP 10.0.2.149.64526 > ip-10-0-1-55.ap-northeast-3.compute.internal.33448: UDP, length 32 11:17:40.882063 IP 10.0.2.149.29773 > ip-10-0-1-55.ap-northeast-3.compute.internal.33449: UDP, length 32 11:17:40.884336 IP 10.0.2.149.48575 > ip-10-0-1-55.ap-northeast-3.compute.internal.33450: UDP, length 32 11:17:40.884347 IP 10.0.2.149.15369 > ip-10-0-1-55.ap-northeast-3.compute.internal.33451: UDP, length 32 11:17:40.884370 IP 10.0.2.149.22250 > ip-10-0-1-55.ap-northeast-3.compute.internal.33452: UDP, length 32
同一 VPC 内の通信で NAT Gateway を経由させることができました。
送信元インスタンスからの Ping
せっかくなので Ping も実行してみます。
もちろん問題なく成功します。
sh-4.2$ date +%H:%M:%S.%6N && ping 10.0.1.55 -c 3 11:19:51.280053 PING 10.0.1.55 (10.0.1.55) 56(84) bytes of data. 64 bytes from 10.0.1.55: icmp_seq=1 ttl=254 time=0.987 ms 64 bytes from 10.0.1.55: icmp_seq=2 ttl=254 time=0.199 ms 64 bytes from 10.0.1.55: icmp_seq=3 ttl=254 time=0.208 ms --- 10.0.1.55 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2026ms rtt min/avg/max/mdev = 0.199/0.464/0.987/0.370 ms sh-4.2$
宛先インスタンス側の tcpdump でも同じように確認できます。
11:19:51.285069 IP 10.0.2.149 > ip-10-0-1-55.ap-northeast-3.compute.internal: ICMP echo request, id 31391, seq 1, length 64 11:19:51.285094 IP ip-10-0-1-55.ap-northeast-3.compute.internal > 10.0.2.149: ICMP echo reply, id 31391, seq 1, length 64 11:19:52.286277 IP 10.0.2.149 > ip-10-0-1-55.ap-northeast-3.compute.internal: ICMP echo request, id 31391, seq 2, length 64 11:19:52.286298 IP ip-10-0-1-55.ap-northeast-3.compute.internal > 10.0.2.149: ICMP echo reply, id 31391, seq 2, length 64 11:19:53.311180 IP 10.0.2.149 > ip-10-0-1-55.ap-northeast-3.compute.internal: ICMP echo request, id 31391, seq 3, length 64 11:19:53.311203 IP ip-10-0-1-55.ap-northeast-3.compute.internal > 10.0.2.149: ICMP echo reply, id 31391, seq 3, length 64
host で 送信元インスタンスの IP を指定して tcpdump
ここまでは NAT Gateway の IP を指定して tcpdump をしていましたが、送信元インスタンスの IP を指定して試してみます。
送信元インスタンスから宛先サブネットへの通信は常に NAT Gateway を経由しているため、通信は発生していないはずです。
sh-4.2$ sudo tcpdump -i eth0 host 10.0.0.11 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
送信元インスタンスから再度 Ping を実行します。
sh-4.2$ date +%H:%M:%S.%6N && ping 10.0.1.55 -c 3 11:21:32.928691 PING 10.0.1.55 (10.0.1.55) 56(84) bytes of data. 64 bytes from 10.0.1.55: icmp_seq=1 ttl=254 time=0.440 ms 64 bytes from 10.0.1.55: icmp_seq=2 ttl=254 time=0.258 ms 64 bytes from 10.0.1.55: icmp_seq=3 ttl=254 time=0.209 ms --- 10.0.1.55 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2044ms rtt min/avg/max/mdev = 0.209/0.302/0.440/0.100 ms sh-4.2$
宛先インスタンスの tcpdump では、何も出力されていませんでした。想定通りです。
宛先インスタンスの SecuriryGroup のインバウンドを制限して Ping
これまで 宛先インスタンスの SecuriryGroup では VPC(10.0.0.0/16)からのインバウンドを許可するようにしていましたが、送信元サブネット(10.0.0.0/24)からのインバウンドのみ許可するように設定変更してみます。
パケットの気持ちになって考えると、宛先インスタンスに到達する際の送信元 IP アドレスは NAT Gateway の持つ 10.0.2.194 です。そこからのインバウンドが許可されていないと通信はブロックされるはずです。
SecuriryGroup の設定変更後、送信元インスタンスから Ping を行います。
sh-4.2$ date +%H:%M:%S.%6N && ping 10.0.1.55 -c 3 11:22:36.676545 PING 10.0.1.55 (10.0.1.55) 56(84) bytes of data. --- 10.0.1.55 ping statistics --- 3 packets transmitted, 0 received, 100% packet loss, time 2040ms sh-4.2$
すべてのパケットがロストしました。これも想定通りです。
ちなみに:NAT Gateway は Ping に応答しない
今回の本旨からは外れますが、NAT Gateway を宛先にして Ping を実行してみました。
sh-4.2$ date +%H:%M:%S.%6N && ping 10.0.2.149 -c 3 11:24:38.673278 PING 10.0.2.149 (10.0.2.149) 56(84) bytes of data. --- 10.0.2.149 ping statistics --- 3 packets transmitted, 0 received, 100% packet loss, time 2028ms
すべてのパケットがロストしました。 ICMP も NAT してくれるものの、自身を宛先にした通信には応答しない、ということが分かりました。
わたしの行為に意味を与えてください
east - west traffic こと VPC 内部の通信を、 NAT Gateway を経由させてみました。
ひとしきりやってみましたが、いまだに使い道は思いついていません。このままだとわたしがただ単に意味が無い行為に手を染めたということになってしまいます。
それはそれで(とても)楽しいのでいいのですが、せっかくなら意味があったほうが嬉しいので、ユースケースが思い付いた方は教えてください。
ひとまず今回は「より具体的なルート」の宛先に NAT Gateway を指定してもきちんと動作する、というところまで持ち帰っていただければと思います。
以上、 チバユキ (@batchicchi) がお送りしました。